#!/usr/bin/env node
import path from "node:path";
import process from "node:process";
import { tasks, listTasks } from "./tasks";
import { TaskResult } from "./types";
import { readSpec, WORKFLOW_ROOT, writeLog, appendMetrics, formatDuration, ensureDir } from "./utils";

interface RunOptions {
  task: string;
  specPath: string;
}

export async function runTask(options: RunOptions): Promise<string> {
  const spec = await readSpec(options.specPath);
  const handler = tasks[options.task];
  if (!handler) {
    throw new Error(`Task ${options.task} not registered`);
  }

  const workspaceDir = path.join(WORKFLOW_ROOT, "workspace", spec.component ?? "default");
  await ensureDir(workspaceDir);

  const startedAt = Date.now();
  const result: TaskResult = await handler(spec, { rootDir: WORKFLOW_ROOT, workspaceDir });
  const duration = formatDuration(startedAt);
  const metrics = result.metrics ?? spec.metrics ?? {};
  const logPath = await writeLog(spec.component ?? "unknown", options.task, {
    task: options.task,
    component: spec.component,
    phase: spec.phase,
    result,
    duration,
  });

  await appendMetrics(
    [
      spec.component ?? "unknown",
      options.task,
      spec.phase ?? "",
      metrics.tokenBefore ?? "",
      metrics.tokenAfter ?? "",
      duration,
      new Date().toISOString(),
      logPath,
    ].join(","),
  );

  return logPath;
}

function parseArgs(args: string[]): Record<string, string> {
  const parsed: Record<string, string> = {};
  for (let i = 0; i < args.length; i++) {
    const arg = args[i];
    if (arg.startsWith("--")) {
      const key = arg.slice(2);
      const value = args[i + 1];
      parsed[key] = value;
      i += 1;
    }
  }
  return parsed;
}

async function cli() {
  const [, , command, ...rest] = process.argv;
  if (!command || ["-h", "--help"].includes(command)) {
    printHelp();
    return;
  }

  if (command === "list") {
    for (const task of listTasks()) {
      process.stdout.write(`${task}\n`);
    }
    return;
  }

  if (command === "run") {
    const args = parseArgs(rest);
    if (!args.task || !args.spec) {
      throw new Error("--task and --spec are required");
    }
    const logPath = await runTask({ task: args.task, specPath: args.spec });
    process.stdout.write(`${logPath}\n`);
    return;
  }

  throw new Error(`Unknown command: ${command}`);
}

function printHelp() {
  process.stdout.write(`Usage:\n`);
  process.stdout.write(`  node scripts/executor/index.js list\n`);
  process.stdout.write(`  node scripts/executor/index.js run --task <task> --spec <path>\n`);
}

if (require.main === module) {
  cli().catch((error) => {
    console.error(error);
    process.exit(1);
  });
}
